package se.webbzon.oschi01.worldcamera;

import java.awt.Dimension;

import se.webbzon.oschi01.worldarea.WorldAppearance3D;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldarea.WorldEngine;
import se.webbzon.oschi01.worldarea.WorldEngineListener;

public class WorldViewFactory {
	
	// View factory properties
	public final static int	TRANSPARENCY	= (1<<0);
	
	// The properties of this world view factory
	private final int properties;
	
	// The world engine associated with this factory
	private final WorldEngine engine;
	
	// The branch group used to contain view specific groups
	// a link to the physical world
	//private final BranchGroup universe;
	
	// A link to the physical universe
	//private final Link physicalUniverse;
	
	//public static SimpleUniverse uni;
	
	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new WorldViewFactory associated with a given world engine. **/
	public WorldViewFactory(int viewFactoryProperties, WorldEngine engine) {
		this.engine = engine;
		properties = viewFactoryProperties;
		/*
		final SimpleUniverse u = new SimpleUniverse();
		//uni = u;
		final Locale locale = new Locale(u);
		
		universe = new BranchGroup();
		universe.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
		universe.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
		
		Link physicalUniverse = new Link();
		physicalUniverse.setCapability(Link.ALLOW_SHARED_GROUP_WRITE);
		physicalUniverse.setCapability(Link.ALLOW_SHARED_GROUP_READ);
		universe.addChild(physicalUniverse);
		int d;
		universe.compile();
		
		locale.addBranchGraph(universe);
		engine.addListener(new EngineListener(physicalUniverse));
		
		if (engine.getWorld() != null)
			physicalUniverse.setSharedGroup(engine.getWorld().getNode().getSharedGroup());*/
	}
	
	/** Creates a new WorldViewFactory associated with a given world engine and a world engine timer. **/
	/*public WorldViewFactory(int viewFactoryProperties, WorldEngine engine, WorldEngineTimer timer) {
		this(viewFactoryProperties,engine);
		universe.addChild(timer.makeNode());
	}*/
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Creates a new WorldView with a given dimension. **/
	public DefaultWorldView makeView(Dimension d) {
		return new WorldViewImpl(	engine, isSet(properties,TRANSPARENCY) ? 
									DefaultWorldView.TRANSPARENCY : 0,
									d);
	}
	
	/** Creates a new JWorldView with a given dimension. **/
	public JWorldView makeJView(Dimension d) {
		return new JWorldViewImpl(	engine, isSet(properties,TRANSPARENCY) ? 
									JWorldView.TRANSPARENCY : 0,
									d);
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Returns true if the given property is set in the given properties. **/
	private static final boolean isSet(int properties, int property) {
		return ((properties & property) == property);
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	/** An implementation of a WorldEngineListener. **/
	private static class EngineListener implements WorldEngineListener {
		
		private final int properties;
		
		private final WorldView view;
		
		public EngineListener(int appearanceProperties, WorldView view) {
			properties = appearanceProperties;
			this.view = view;
		}
		
		/*============================================================
		Public Methods
		============================================================*/
		
		@Override public void onSetWorldArea(WorldArea world) {
			view.setWorld(world.getAppearance());
		}
		
	}
	
	/** An implementation of the abstract class WorldView. **/
	private static class WorldViewImpl extends DefaultWorldView {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = 6069165068820380542L;
		
		/*============================================================
		Constructors
		============================================================*/

		public WorldViewImpl(WorldEngine engine, int viewProperties, Dimension d) {
			super(viewProperties,d);
			engine.addListener(new EngineListener(viewProperties,this));
			WorldArea w = engine.getWorld();
			if (w != null)
				setWorld(w.getAppearance());
		}
		
	}
	
	/** An implementation of the abstract class JWorldView. **/
	private static class JWorldViewImpl extends JWorldView {

		// Auto generated serial version UID
		private static final long serialVersionUID = 2403758181978973606L;
		
		/*============================================================
		Constructors
		============================================================*/

		public JWorldViewImpl(WorldEngine engine, int viewProperties, Dimension d) {
			super(viewProperties,d);
			engine.addListener(new EngineListener(viewProperties,this));
			WorldArea w = engine.getWorld();
			if (w != null)
				setWorld(w.getAppearance());
		}
		
	}

}
